package cc.linker.steplink.crm.merchant.util;

import cc.linker.steplink.crm.response.GlobalException;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.net.ftp.FTPClient;
import org.apache.commons.net.ftp.FTPReply;
import org.springframework.util.StringUtils;

import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.List;
import java.util.Map;
import java.util.concurrent.atomic.AtomicReference;

@Slf4j
public class FTPUtil {
    /**
     * 连接 FTP 服务器
     *
     * @param addr     FTP 服务器 IP 地址
     * @param port     FTP 服务器端口号
     * @param username 登录用户名
     * @param password 登录密码
     * @return
     * @throws Exception
     */
    public static FTPClient connectFtpServer(String addr, int port, String username, String password, String controlEncoding) {
        FTPClient ftpClient = new FTPClient();
        try {
            /**设置文件传输的编码*/
            ftpClient.setControlEncoding(controlEncoding);

            /**连接 FTP 服务器
             * 如果连接失败，则此时抛出异常，如ftp服务器服务关闭时，抛出异常：
             * java.net.ConnectException: Connection refused: connect*/
            ftpClient.connect(addr, port);
            /**登录 FTP 服务器
             * 1）如果传入的账号为空，则使用匿名登录，此时账号使用 "Anonymous"，密码为空即可*/
            if (StringUtils.isEmpty(username)) {
                ftpClient.login("Anonymous", "");
            } else {
                ftpClient.login(username, password);
            }

            /** 设置传输的文件类型
             * BINARY_FILE_TYPE：二进制文件类型
             * ASCII_FILE_TYPE：ASCII传输方式，这是默认的方式
             * ....
             */
            ftpClient.setFileType(FTPClient.BINARY_FILE_TYPE);

            /**
             * 主动模式
             */
//            ftpClient.enterLocalActiveMode();
            /**
             * 被动模式
             */
            ftpClient.enterLocalPassiveMode();

            /**
             *
             * 确认应答状态码是否正确完成响应
             * 凡是 2开头的 isPositiveCompletion 都会返回 true，因为它底层判断是：
             * return (reply >= 200 && reply < 300);
             */
            int reply = ftpClient.getReplyCode();
            if (!FTPReply.isPositiveCompletion(reply)) {
                /**
                 * 如果 FTP 服务器响应错误 中断传输、断开连接
                 * abort：中断文件正在进行的文件传输，成功时返回 true,否则返回 false
                 * disconnect：断开与服务器的连接，并恢复默认参数值
                 */
                ftpClient.abort();
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            throw GlobalException.build(">>>>>FTP服务器连接登录失败，请检查连接参数是否正确，或者网络是否通畅*********");
        }
        return ftpClient;
    }

    /**
     * 使用完毕，应该及时关闭连接
     * 终止 ftp 传输
     * 断开 ftp 连接
     *
     * @param ftpClient
     * @return
     */
    public static FTPClient closeFTPConnect(FTPClient ftpClient) {
        try {
            if (ftpClient != null && ftpClient.isConnected()) {
                ftpClient.abort();
                ftpClient.disconnect();
            }
        } catch (IOException e) {
            throw GlobalException.build(">>>>>断开FTP服务器连接，请检查连接参数是否正确，或者网络是否通畅*********");
        }
        return ftpClient;
    }


    /**
     * 上传本地文件 或 目录 至 FTP 服务器----保持 FTP 服务器与本地 文件目录结构一致
     * 返回值  1 链接失效  2 文件不存在  3 ftp目录创建失败 0 成功
     *
     * @param ftpClient 连接成功有效的 FTPClinet
     * @param picUrl    图片链接 picUrl
     * @param fileName  图片名称 fileName
     * @throws Exception
     */
    public static Boolean uploadFiles(FTPClient ftpClient, String picUrl, String fileName) {
        if (!ftpClient.isConnected() || !ftpClient.isAvailable()) {
            LOGGER.info(">>>>>FTP服务器连接已经关闭或者连接无效*****放弃文件上传****");
            return false;
        }
        boolean storeFileStatus = false;
        try {
            URL url = new URL(picUrl);
            HttpURLConnection con = (HttpURLConnection) url.openConnection();
            con.setRequestMethod("GET");
            con.setConnectTimeout(4 * 1000);
            InputStream input = con.getInputStream();//通过输入流获取图片数据   
            storeFileStatus = ftpClient.storeFile(fileName, input);
            input.close();
            LOGGER.info(">>>>>文件上传****"+picUrl+";fileName:"+fileName+";storeFileStatus:"+storeFileStatus);
            LOGGER.info("replay->>code:"+ftpClient.getReplyCode()+",String:"+ftpClient.getReplyString());
        } catch (IOException e) {
            throw GlobalException.build(">>>>>FTP上传文件失败，请检查连接参数是否正确，或者网络是否通畅*********");
        }
        return storeFileStatus;
    }

    public static void changeWorkingDir(FTPClient ftpClient, String remoteDir) {
        try {
            // 进入指定目录
            if (!StringUtils.isEmpty(remoteDir)) {
                // 判断目录是否存在 ，不存在创建
                if (!ftpClient.changeWorkingDirectory(remoteDir)) {
                    // 创建目录
                    if (!ftpClient.makeDirectory(remoteDir)) {
                        LOGGER.info(">>>>>目录不存在*****目录创建失败****");
                        throw GlobalException.build(">>>>>FTP创建目录失败，请检查连接参数是否正确，或者网络是否通畅*********");
                    }
                    ftpClient.changeWorkingDirectory(remoteDir);
                }
            }
        } catch (IOException e) {
            throw GlobalException.build(">>>>>FTP创建目录失败，请检查连接参数是否正确，或者网络是否通畅*********");
        }
    }

    /**
     * 网络图片 上传到 指定FTP目录
     *
     * @param host     ftp host
     * @param port     ftp port
     * @param userName ftp userName
     * @param passWord ftp passWord
     * @param fileList fileUrl,fileName,remoteDir
     */
    public static Boolean uploadFtp(String host, Integer port, String userName, String passWord, String remoteDir, List<Map<String, Object>> fileList) {
        LOGGER.info("FTP->>host:"+host+",port:"+port+",userName:"+userName+",passWord:"+passWord+",remoteDir:"+remoteDir);
        //建立ftp链接
        AtomicReference<Boolean> result = new AtomicReference<>(true);
        FTPClient ftpClient = connectFtpServer(host, port, userName, passWord, "gbk");
        changeWorkingDir(ftpClient, remoteDir);
        fileList.forEach(x -> {
            String fileUrl = x.get("fileUrl").toString();
            String fileName = x.get("fileName").toString();
            // 上传ftp
            boolean uploadStatus = uploadFiles(ftpClient, fileUrl, fileName);
            if (!uploadStatus) {
                result.set(false);
            }
        });
        // 关闭ftp链接
        closeFTPConnect(ftpClient);
        return result.get();
    }

//    /**
//     * 上传地址        139.196.12.148
//     * 端口        21
//     * FTP账号        2002281309404491347
//     * FTP密码        123456
//     * @param args
//     */
//
//    public static void main(String[] args) {
//        FTPClient ftpClient = connectFtpServer("139.196.12.148", 21, "2002281309404491347", "123456", "gbk");
//        changeWorkingDir(ftpClient, "test");
//        boolean uploadStatus = uploadFiles(ftpClient, "https://hzlh-test.linker.cc/StepLink/202005/12/15/HhFcqUKrrBuOfvgYZIpLaIXxgZAgT4DlLmyh2020051215187.jpg", "test.jpg");
//        closeFTPConnect(ftpClient);
//    }
}

